//
// Created by hay boy on 2022/7/4.
//

#ifndef ALGORITHMS_LINKEDQUEUE_H
#define ALGORITHMS_LINKEDQUEUE_H
#include "Queue.h"
#include <sstream>
#include "QueueException.h"
#include "../chainNode/ChainNode.h"

using namespace std;

template<class T>
class LinkedQueue : public Queue<T> {
public:
    explicit LinkedQueue(int initialCapacity = 10){
        queueFront = nullptr;
        queueSize = 0;
    }
    ~LinkedQueue();
    bool empty()const{
        return queueSize == 0;
    }
    int size()const{
        return queueSize;
    }
    T& front(){
        if(queueSize==0){
            throw QueueEmpty();
        }
        return queueFront->element;
    }
    T& back(){
        if(queueSize==0){
            throw QueueEmpty();
        }
        return queueBack->element;
    }
    void pop();
    void push(const T&);
private:
    ChainNode<T>* queueFront;
    ChainNode<T>* queueBack;
    int queueSize;
};

template<class T>
LinkedQueue<T>::~LinkedQueue() {
    while(queueFront!= nullptr){
        ChainNode<T>* nextNode = queueFront->next;
        delete queueFront;
        queueFront = nextNode;
    }
}

template<class T>
void LinkedQueue<T>::pop() {
    if(queueFront== nullptr){
        throw QueueEmpty();
    }
    ChainNode<T>* nextNode = queueFront->next;
    delete queueFront;
    queueFront = nextNode;
    queueSize--;
}

template<class T>
void LinkedQueue<T>::push(const T &theElement) {
    ChainNode<T>* newNode = new ChainNode<T>(theElement, nullptr);
    if(queueSize==0){
        queueFront = newNode;
    }else{
        queueBack->next = newNode;
    }
    queueBack = newNode;
    queueSize++;
}

#endif //ALGORITHMS_LINKEDQUEUE_H
